import _ from "lodash"

// 如果对象很简单只有一层
// 可以使用析构表达式或者使用Object.align
let a = {
    name:"lin",
    age:"20",
    sex:"male"
};

let b = {...a};

a.name = "ren";
console.log(b);


// 如果对象结构复杂可以使用序列化的方法
let bank = {
    name: "hello bank",
    ceo: {
        name: "lin",
        age: 20,
        son: {
            name: "bob",
            age: 1,
        }
    }
};

let obank = JSON.parse(JSON.stringify(bank));

bank.ceo.name = "ren";
console.log(obank.ceo.name);

// 但是JSON序列化只会序列化普通的属性 像是函数 Symbol undefined 以及 循环引用的问题都不能完成拷贝
let badGuy ={
    name: null,
    age: undefined,
    kill() {
        console.log("kill someone!");
    },
    id: Symbol("killer")
}

let goodGuy = JSON.parse(JSON.stringify(badGuy));
console.log(goodGuy);


// 也可以使用消息队列的方法来深拷贝
// function structuralClone(obj) {
//     return new Promise(resolve => {
//       const { port1, port2 } = new MessageChannel()
//       port2.onmessage = ev => resolve(ev.data)
//       port1.postMessage(obj)
//     })
//   }
  
//   var obj = {
//     a: 1,
//     b: {
//       c: 2
//     }
//   }
  
//   obj.b.d = obj.b
  
//   // 注意该方法是异步的
//   // 可以处理 undefined 和循环引用对象
//   const test = async () => {
//     const clone = await structuralClone(obj)
//     console.log(clone)
//   }
//   test()


// 我们可以自己写一个递归的深拷贝，

const isObj = function(obj) {
    return (typeof obj === "object" || typeof obj === "function");
}
const isArray = function(obj) {
    return Array.isArray(obj);
}

function deepClone(obj) {
    if(!isObj(obj)) {
        console.log("%cwarn: not a object","color:yellow");
        return obj;
    }
    let newObj = isArray(obj)?[...obj]:{...obj};
    // Reflect.ownKeys 可以返回不可枚举的属性
    Reflect.ownKeys(obj).map(key => {
        newObj[key] = isObj(obj[key])?deepClone(obj[key]):obj[key];
    });
    return newObj;
}
let dog = {
    name: "阿拉斯加",
    age: 1,
};
let myDog = deepClone(dog);
dog.name = "柯基";
console.log(myDog);


// 但是深拷贝有很多的坑点，比如原型链，DOM元素等等，为了安全我们可以使用loadsh实现的深拷贝函数
var objects = [{ 'a': 1 }, { 'b': 2 }];
 
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
